package com.first.wchat.notify;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import com.first.wchat.data.Constant;
import com.first.wchat.data.NotifyData;

public class Notifier { 

	public final int START = 0x00;
	public final int PAUSE = 0x10;
	public final int STOP  = 0x20;
	byte[] lock = new byte[0];
	Thread mDispatcher;
	Thread mReceiver;
	int state = -1;
	ArrayList<InetAddress> mDevices = new ArrayList<InetAddress>();
	NotifyListener mListener;
	boolean isNeedNotify = true;
	Timer mNotifyTimer;
	
	static Notifier mInstance;
	public interface NotifyListener
	{
		public void refrash(ArrayList<InetAddress> devices);
	}
	
	
	public static Notifier getInstance()
	{
		if(mInstance == null)
			mInstance = new Notifier();
		return mInstance;
	}
	
	private Notifier()
	{
		createDispatcher();
		createReciver();
	}
	
	public void setNotifyListener(NotifyListener l)
	{
		mListener = l;
	}
	
	
	public boolean isRunning()
	{
		return state == START;
	}
	
	
	public void pause()
	{
		state = PAUSE;
		if(mNotifyTimer!=null)
			mNotifyTimer.cancel();
		synchronized(lock)
		{
			lock.notifyAll();
		}
	}
	
	public void stop()
	{
		state = STOP;
		if(mNotifyTimer!=null)
			mNotifyTimer.cancel();
		
	}
	
	public void start()
	{
		if(state!=START)
		{

			mNotifyTimer = null;
			state = START;
			isNeedNotify = true;
			mDispatcher.start();
			mReceiver.start();
		}
	}
	
	
	
	private void createDispatcher()
	{
		mDispatcher = new Thread(new Runnable()
		{

			@Override
			public void run() {
				
				while(state!= STOP)
				{
					
					if(state == PAUSE)
					{
						synchronized(lock)
						{
							try {
								lock.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					
					String message= NotifyData.getData();
			        int server_port = Constant.NOTIFYPORT;  
			        DatagramSocket s = null;  
			        try {  
			            s = new DatagramSocket();  
			        } catch (SocketException e) {  
			            e.printStackTrace();  
			        }  
			        InetAddress local = null;  
			        try {  
			            local = InetAddress.getByName("255.255.255.255");  
			        } catch (UnknownHostException e) {  
			            e.printStackTrace();  
			        }  
			        int msg_length = message.length();  
			        byte[] messageByte = message.getBytes();  
			        DatagramPacket p = new DatagramPacket(messageByte, msg_length, local,  
			                server_port);  

			        try {  
			            s.send(p);  
			        } catch (IOException e) {  
			            e.printStackTrace();  
			            s.close();
			        }  
			        
			        s.close();
			        
			        if(isNeedNotify)
			        {
			        	if(mNotifyTimer!=null)
							mNotifyTimer.cancel();
			        	mNotifyTimer =new Timer();
			        	mNotifyTimer.schedule(new TimerTask(){
	
							@Override
							public void run() {
								if(mListener!=null)
									mListener.refrash(mDevices);
							}
			         		
			         	}, 3000,30000);
			        }
			        isNeedNotify = false;
			        try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}
			
		});
	}
	
	private void createReciver()
	{
		
		mReceiver = new Thread(new Runnable()
		{

			@Override
			public void run() { 
				Integer port = Constant.NOTIFYPORT;  
		        byte[] message = new byte[1024];  
		        DatagramSocket datagramSocket = null;
		        try {  
		            datagramSocket = new DatagramSocket(port);  
		            DatagramPacket datagramPacket = new DatagramPacket(message,message.length);  
		            try {  
		                while (state!= STOP) {  

		                    datagramSocket.receive(datagramPacket);  
		                    String msg = new String(datagramPacket.getData());
		                    if(msg.startsWith(Constant.NITIFYHEAD))
		                    {
			                    InetAddress newIA = datagramPacket.getAddress();
			                    if(!mDevices.contains(newIA))
			                    {
			                    	mDevices.add(newIA);
			                    }
		                    }
 
		                }  
		            } catch (IOException e) {  
		                e.printStackTrace();  
		                datagramSocket.close();
		               
		            }  
		        } catch (SocketException e) {  
		            e.printStackTrace();  
		            if(datagramSocket!=null)
		            	datagramSocket.close();
		        } 	
			}
			
		});
		
	}

}
